package com.durian.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.durian.config.ServiceException;
import com.durian.domain.DTO.ObsAddressAddDTO;
import com.durian.domain.DTO.ObsAddressUpdateDTO;
import com.durian.domain.DTO.ObsDefaultListDTO;
import com.durian.domain.VO.ObsAddressListVO;
import com.durian.domain.entity.ObsAddress;
import com.durian.domain.entity.ObsUser;
import com.durian.enums.AddressStatus;
import com.durian.mapper.ObsAddressMapper;
import com.durian.mapper.ObsUserMapper;
import com.durian.service.IObsAddressService;
import com.durian.utils.BeanListUtils;
import com.durian.utils.PageInfoResult;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 用户地址表 服务实现类
 * </p>
 *
 * @author Durian
 * @since 2023-11-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ObsAddressServiceImpl extends ServiceImpl<ObsAddressMapper, ObsAddress> implements IObsAddressService {

    @Value("${default.pageNum}")
    private Integer pageNum;

    @Value("${default.pageSize}")
    private Integer pageSize;

    private final ObsAddressMapper addressMapper;

    private final ObsUserMapper userMapper;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public PageInfoResult<ObsAddressListVO> listAddress(ObsDefaultListDTO defaultListDTO) {

        String searchMessage = defaultListDTO.getSearchMessage();
        Integer pageNum = defaultListDTO.getPageNum();
        Integer pageSize = defaultListDTO.getPageSize();

        // 设置查询条件
        LambdaQueryWrapper<ObsAddress> listAddressWrapper = new LambdaQueryWrapper<ObsAddress>()
                .like(StringUtils.isNotBlank(searchMessage), ObsAddress::getAddress, searchMessage)
                .or(StringUtils.isNotBlank(searchMessage), i -> i
                        .like(ObsAddress::getAddressDetail, searchMessage)
                        .like(ObsAddress::getAddressContact, searchMessage)
                );

        // 检查分页页码和大小
        if (ObjectUtils.isNull(pageNum)) {
            pageNum = this.pageNum;
        }
        if (ObjectUtils.isNull(pageSize)) {
            pageSize = this.pageSize;
        }

        // 进行分页查询并对数据处理
        return PageInfoResult.of(PageHelper.startPage(pageNum, pageSize)
                .doSelectPageInfo(() ->
                        addressMapper.selectList(listAddressWrapper)
                ), ObsAddressListVO.class);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<ObsAddressListVO> listAddress(Long userId) {

        LambdaQueryWrapper<ObsAddress> listAddressWrapper = new LambdaQueryWrapper<ObsAddress>()
                .eq(ObsAddress::getUserId, userId);

        List<ObsAddress> addresses = addressMapper.selectList(listAddressWrapper);
        return BeanListUtils.copyListUtil(addresses, ObsAddressListVO.class);
    }


    @Override
    @Transactional
    public void addAddress(ObsAddressAddDTO addressAddDTO) {

        // 新建地址对象
        ObsAddress address = new ObsAddress();
        // 复制DTO信息到地址对象
        BeanUtils.copyProperties(addressAddDTO, address);

        Long userId = address.getUserId();
        String addressContact = address.getAddressContact();
        String addressPhone = address.getAddressPhone();

        // 检查用户是否存在
        LambdaQueryWrapper<ObsUser> getUserWrapper = new LambdaQueryWrapper<ObsUser>()
                .eq(ObsUser::getUserId, userId);
        ObsUser user = userMapper.selectOne(getUserWrapper);
        if (ObjectUtils.isNull(user)) {
            throw new ServiceException("用户不存在!!");
        }

        // 如果联系方式或联系人为空则默认使用用户的信息
        if (StringUtils.isBlank(addressContact)) {
            address.setAddressContact(user.getUserName());
        }
        if (StringUtils.isBlank(addressPhone)) {
            address.setAddressPhone(user.getUserTel());
        }

        int insertAddress = addressMapper.insert(address);
        if (insertAddress != 1) {
            log.error("数据库未知:{} = addressMapper.insert()", insertAddress);
            throw new ServiceException("系统错误");
        }
    }

    @Override
    @Transactional
    public void updateAddress(ObsAddressUpdateDTO address) {

        Long addressId = address.getAddressId();
        Long userId = address.getUserId();
        String Address = address.getAddress();
        String addressDetail = address.getAddressDetail();
        String addressContact = address.getAddressContact();
        String addressPhone = address.getAddressPhone();
        AddressStatus addressStatus = address.getAddressStatus();

        // 检查用户是否存在
        LambdaQueryWrapper<ObsUser> userExistWrapper = new LambdaQueryWrapper<ObsUser>()
                .select(ObsUser::getUserId)
                .eq(ObsUser::getUserId, userId);
        if (!userMapper.exists(userExistWrapper)) {
            throw new ServiceException("用户不存在");
        }
        // 检查地址是否存在
        LambdaQueryWrapper<ObsAddress> addressExistWrapper = new LambdaQueryWrapper<ObsAddress>()
                .select(ObsAddress::getAddressId)
                .eq(ObsAddress::getAddressId, addressId);
        if (!addressMapper.exists(addressExistWrapper)) {
            throw new ServiceException("地址不存在");
        }

        LambdaUpdateWrapper<ObsAddress> updateAddressWrapper = new LambdaUpdateWrapper<ObsAddress>()
                .set(StringUtils.isNotBlank(Address), ObsAddress::getAddress, Address)
                .set(StringUtils.isNotBlank(addressDetail), ObsAddress::getAddressDetail, addressDetail)
                .set(StringUtils.isNotBlank(addressContact), ObsAddress::getAddressContact, addressContact)
                .set(StringUtils.isNotBlank(addressPhone), ObsAddress::getAddressPhone, addressPhone)
                .set(ObjectUtils.isNotNull(addressStatus), ObsAddress::getAddressStatus, addressStatus)
                .eq(ObsAddress::getAddressId, addressId)
                .eq(ObsAddress::getUserId, userId);

        // 更新用户地址
        int updateAddress = addressMapper.update(new ObsAddress(), updateAddressWrapper);
        if (updateAddress != 1) {
            log.error("数据库未知:{} = addressMapper.update({})", updateAddress, updateAddressWrapper.getSqlSet());
            throw new ServiceException("系统错误");
        }
    }

    @Override
    @Transactional
    public void removeAddress(List<Long> ids) {

        // 检查地址是否存在
        ids.forEach(id -> {
            LambdaQueryWrapper<ObsAddress> addressExistWrapper = new LambdaQueryWrapper<ObsAddress>()
                    .select(ObsAddress::getAddressId)
                    .eq(ObsAddress::getAddressId, id);
            if (!addressMapper.exists(addressExistWrapper)) {
                throw new ServiceException("有个地址已移除");
            }
        });

        LambdaUpdateWrapper<ObsAddress> removeAddressWrapper = new LambdaUpdateWrapper<ObsAddress>()
                .in(ObsAddress::getAddressId, ids);

        // 移除地址
        int removeAddress = addressMapper.delete(removeAddressWrapper);
        if (removeAddress <= 0) {
            log.error("数据库未知:{} = addressMapper.delete()", removeAddress);
            throw new ServiceException("系统错误");
        }
    }
}
